from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand, CommandError
from django.core import serializers
from django.utils.datastructures import SortedDict

from optparse import make_option

import os, subprocess
from nutrition.migration import dynamic_import, FORM_DICT, MIGRATION_TASKS

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--key', default='', dest='key', type='str',
            help='Specifies the key of the corresponding csv file.'),
        make_option('--start', default=0, dest='start', type='int',
            help='Specifies the starting row of the csv file.'),
        make_option('--end', default=None, dest='end', type='int',
            help='Specifies the ending row of the csv file'),
        make_option('--threshold', default=2000, dest='THRESHOLD', type='int',
            help='Specifies the maximum number of rows for a individual process to handle.'),
        make_option('-f', action="store_true", dest="force",
            help='Specifies the maximum number of rows for a individual process to handle.'),
    )
    help = 'Resolve relationships of the imported data from the sr21 USDA National Nutrient Database.'
    
    def handle(self, **options):
        key       = options.get('key',       None)
        start     = options.get('start',     0)
        end       = options.get('end',       None)
        THRESHOLD = options.get('THRESHOLD', 2000)
        force     = options.get('force',     False)
        PWD       = os.environ['PWD']
        
        if key:
            if key not in FORM_DICT.keys():
                raise CommandError("Invalid key specified. Key choices are: %s" % FORM_DICT.keys())
            value = FORM_DICT[key]
            
            # Dynamically import the corresponding module and get the Form attribute
            module = dynamic_import('nutrition.forms')
            form = getattr(module, value['form_name'])
            
            # If an end value is provided, ignore the total count
            if end:
                length = end - start
            else:
                # Determine a row count from the total objects
                count  = form._meta.model.objects.count()
                length = count - start
            
            if length > THRESHOLD:
                num_segments = int(round(length / THRESHOLD))
                
                command_set = []
                for multiplier in range(0, num_segments + 1):
                    cmd = [
                        PWD + '/manage.py',
                        'resolve_sr21',
                        '--key=%s' % key,
                        '--start=%s' % (int(start) + THRESHOLD * multiplier),
                        '--end=%s' % (int(start) + THRESHOLD * (multiplier + 1)),
                        '--threshold=%s' % THRESHOLD,
                    ]
                    if force:
                        cmd.append('-f')
                    command_set.append(cmd)
                
                #print command_set
                for cmd in command_set:
                    p = subprocess.Popen(cmd)
                    p.wait()
            else:
                failures = sum(not obj.resolve_relations(force) for obj in form._meta.model.objects.all()[start:(end or count)])
                if failures:
                    print "%s out of %s unresolved objects" % (failures, length)

        else:
            for source in MIGRATION_TASKS:
                print "%s working..." % source
                cmd = [
                    PWD + '/manage.py',
                    'resolve_sr21',
                    '--key=%s' % source,
                    '--threshold=%s' % THRESHOLD,
                ]
                if force:
                    cmd.append('-f')
                p = subprocess.Popen(cmd)
                p.wait()
                print "%s complete" % source